<?php

class MsggWechat
{
    use util_array;
    const MSG_TYPE_TEXT = 'text';
    const MSG_TYPE_IMAGE = 'image';
    const MSG_TYPE_VOICE = 'voice';
    const MSG_TYPE_VIDEO = 'video';
    const MSG_TYPE_FILE = 'file';
    const MSG_TYPE_NEWS = 'news';

    public static function execute($params, $channelConfs = [])
    {
        $result = array('code' => 0, 'msg' => '', 'detail' => array());
        try {
            $apiParams = array();
            //check to user
            $apiParams['touser'] = empty($params['to']) ? null : (is_array($params['to']) ? implode('|', $params['to']) : $params['to']);
            $apiParams['toparty'] = empty($params['to_party']) ? null : (is_array($params['to_party']) ? implode('|', $params['to_party']) : $params['to_party']);
            if (empty($apiParams['touser']) && !$apiParams['toparty']) {
                throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat to user/party invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
            }
            //check msgType and content
            $msgType = empty($params['msg_type']) ? self::MSG_TYPE_TEXT : $params['msg_type'];
            $apiParams['msgtype'] = $msgType;
            $apiParams[$msgType] = array();
            switch ($msgType) {
                case self::MSG_TYPE_TEXT:
                    $apiParams[$msgType]['content'] = empty($params['content']) ? null : $params['content'];
                    if (empty($apiParams[$msgType]['content'])) {
                        throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat content invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
                    }
                    break;
                case self::MSG_TYPE_IMAGE:
                case self::MSG_TYPE_VOICE:
                case self::MSG_TYPE_FILE:
                    $apiParams[$msgType]['media_id'] = empty($params['media_id']) ? null : $params['media_id'];
                    if (empty($apiParams[$msgType]['media_id'])) {
                        throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat media_id invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
                    }
                    break;
                case self::MSG_TYPE_VIDEO:
                    $apiParams[$msgType]['media_id'] = empty($params['media_id']) ? null : $params['media_id'];
                    $apiParams[$msgType]['title'] = empty($params['title']) ? 'Video Msg From Msgg' : $params['title'];
                    $apiParams[$msgType]['description'] = empty($params['description']) ? null : $params['description'];
                    if (empty($apiParams[$msgType]['media_id'])) {
                        throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat media_id invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
                    }
                    break;
                case self::MSG_TYPE_NEWS:
                    $articles = (empty($params['articles']) || !is_array($params['articles'])) ? array() : $params['articles'];
                    foreach ($articles as $i => $article) {
                        if (empty($article['title']) || empty($article['description']) || empty($article['url']) || empty($article['picurl'])) {
                            continue;
                        }
                        $apiParams[$msgType]['articles'][] = array(
                            'title' => (empty($article['title']) ? 'Title' . $i : $article['title']),
                            'description' => (empty($article['description']) ? '' : $article['description']),
                            'url' => (empty($article['url']) ? '' : $article['url']),
                            'picurl' => (empty($article['picurl']) ? '' : $article['picurl']),
                        );
                    }
                    if (empty($apiParams[$msgType]['articles'])) {
                        throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat articles invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
                    }
                    break;
                default:
                    throw new Exception(MsggItem::ERROR_MSG_ITEM_PARAMS_INVALID . ': wechat msg_type invalid', MsggItem::ERROR_CODE_ITEM_PARAMS_INVALID);
                    break;
            }
            //begin send by channel conf
            $lastResult = false;
            foreach ($channelConfs as $i => $channelConf) {
                $channelResult = MsggWechatClient::sendMsg($apiParams, $channelConf);
                $channelName = implode('_', array(MsggItem::TYPE_WECHAT, (empty($channelConf['name']) ? 'Channel' . $i : $channelConf['name'])));
                $result['detail'][$channelName] = $channelResult;
                //add log
                $attributes = array(
                    'type' => MsggItem::TYPE_WECHAT,
                    'params' => $params,
                    'result' => $channelResult,
                    'channel' => $channelName,
                    'status' => $channelResult['code'] == 0 ? MsggItem::STATUS_SUCCESS : MsggItem::STATUS_FAILURE,
                    'conf' => $channelConf,
                );
                $log = MsggChannelLog::build($attributes);
                $result['logs'][] = $log;
                if (isset($channelResult['code']) && ($channelResult['code'] == 0)) {
                    $result['ext'] = empty($channelResult['ext']) ? array() : $channelResult['ext'];
                    $lastResult = true;
                    break;
                }

            }
            if (!$lastResult) {
                throw new Exception(MsggItem::ERROR_MSG_GATEWAY_FAILURE, MsggItem::ERROR_CODE_GATEWAY_FAILURE);
            }
        } catch (Exception $e) {
            $result['code'] = MsggItem::ERROR_CODE_GATEWAY_FAILURE;
            $result['msg'] = $e->getMessage();
        }
        return $result;
    }

    public static function mapCodeStatus($channelClass, $code)
    {
        return ($code == 0 && $channelClass == MsggWechatClient::class) ? MsggItem::STATUS_SUCCESS : MsggItem::STATUS_FAILURE;
    }

    public static function refreshStatus(MsggItem $item)
    {
        $status = MsggItem::STATUS_FAILURE;
        if ($item != null && !empty($channelLogs =$item->msgChannelLogs)) {
            $channelLog =@end($channelLogs);
            $config = json_decode($channelLog->conf, true);
            $class = self::util_array_get($config, 'class', null);
            $status=$channelLog->status;
            if ($class) {
                if (class_exists($class)) {
                    $available_method = array();
                    foreach (get_class_methods($class) as $method) {
                        $available_methods[strtolower($method)] = $method;
                    }
                    if (empty($available_methods['refreshstatus'])) {
                        Yii::log('refreshStatus method  not exists  in class ' . $class, CLogger::LEVEL_ERROR, 'msggcall.refreshStatus');
                    } else {
                        $ext_status = call_user_func_array(array($class, 'refreshStatus'), array($channelLog));
                        if (!empty($ext_status)) {
                            $channelLog->ext_status = $ext_status;
                            $channelLog->save();
                        }
                    }
                } else {
                    Yii::log('calss not exists ' . $class . ' log id ' . $channelLog->id, CLogger::LEVEL_ERROR, 'msggcall.refreshStatus');
                }
            }
        }
        return $status;
    }

}
